package mySingleList;

import java.util.List;

public class MySingleList<T> implements IList{
    static class ListNode<T>{
        public T val;
        public ListNode<T> next;

        public ListNode(T val) {
            this.val = val;
        }
    }

    public ListNode<T> head;
    @Override
    public void addFirst(Object data) {
        ListNode<T> node = (ListNode<T>) new ListNode<>(data);
        if (this.head != null) {
            node.next = this.head;
        }
        this.head = node;
    }

    @Override
    public void addLast(Object data) {
        ListNode node = new ListNode(data);

        ListNode cur = this.head;
        if(this.head == null)
        {
            this.head = node;
        }
        else
        {
            while(cur.next != null)
            {
                cur = cur.next;
            }
            cur.next = node;
        }
    }

    private void addIndexException(int index) throws mySingleListException
    {
        if(index < 0 || index > this.size())
        {
            throw new mySingleListException("插入下标异常");
        }
    }

    private void serchPrevException(int index) throws mySingleListException
    {
        if(index < 0 || index > this.size())
        {
            throw new mySingleListException("寻找下标异常");
        }
    }

    private ListNode<T> searchPrev(int index)
    {
        this.serchPrevException(index);
        ListNode<T> cur = this.head;
        int count = 0;
        while(count != index - 1)
        {
            cur = cur.next;
            count++;
        }

        return cur;
    }

    @Override
    public void addIndex(int index, Object data) {
        addIndexException(index);

        if(index == 0)
        {
            this.addFirst(data);
            return;
        }
        else if(index == this.size())
        {
            this.addLast(data);
            return;
        }

        ListNode<T> cur = this.searchPrev(index);
        ListNode<T> node = (ListNode<T>) new ListNode<>(data);
        node.next = cur.next;
        cur.next = node;
    }

    @Override
    public boolean contains(Object key) {
        ListNode cur = this.head;
        while(cur != null)
        {
            if(cur.val == key)
            {
                return true;
            }
            cur = cur.next;
        }

        return false;
    }

    private ListNode searchPrev(Object key)
    {
        ListNode cur = this.head;
        while(cur.next != null)
        {
            if(cur.next.val == key)
            {
                return cur;
            }
        }

        return null;
    }
    @Override
    public void remove(Object key) {
        if(this.head == null)
        {
            return;
        }

        if(this.head.val.equals(key))
        {
            this.head = this.head.next;
            return;
        }

        ListNode cur = searchPrev(key);
        if(cur == null)
        {
            return;
        }

        ListNode del = cur.next;
        cur.next = del.next;
    }

    @Override
    public void removeAllKey(Object key) {
        if(this.head == null)
        {
            return;
        }

        ListNode prev = head;
        ListNode cur = head.next;
        while (cur != null)
        {
            if(cur.val.equals(key))
            {
                prev.next = cur.next;
                cur = cur.next;
            }
            else {
                prev = cur;
                cur = cur.next;
            }
        }

        if(head.val.equals(key))
        {
            head = head.next;
        }
    }

    @Override
    public int size() {
        int count = 0;
        ListNode cur = this.head;
        while(cur != null)
        {
            count++;
            cur = cur.next;
        }
        return count;
    }

    @Override
    public void clear() {
        ListNode cur = head;
        while(cur != null)
        {
            ListNode curNext = cur.next;
            cur.next = null;
            cur = curNext;
        }

        head = null;
    }

    @Override
    public void display() {
        ListNode cur = this.head;
        while(cur!=null)
        {
            System.out.print(cur.val + " ");
            cur = cur.next;
        }
        System.out.println();
    }
}
